﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using NPOI.HSSF.UserModel;
using NPOI.SS.Util;
using NPOI.SS.Converter;
using NPOI.XSSF.Util;
using AgingTest.Tools;
using AgingTest.DataProcess;
using System.IO;
using System.Threading;

namespace AgingTest
{
    public partial class FormMain : Form
    {
        /// <summary>
        /// 定义更新消息文本框内容委托
        /// </summary>
        /// <param name="strMsg">定时任务传递过来的消息</param>
        public delegate void ComReceiveMsgEvent(string strMsg,byte[] buff);
        ComReceiveMsgEvent OnComReceiveMsgEvent = null;

        public delegate void ComErrMsgEvent(string strMsg);
        ComErrMsgEvent OnCOMErrMsgEvent = null;

        //定义数据库连接线程
        public delegate void SqlConnThreadMsg(string Msg);
        public bool IsSqlConnection = true;

        //定义定时器
        System.Windows.Forms.Timer TimerMain = new System.Windows.Forms.Timer();
        int TimerCount = 0;
        SendCheckData SendData = new SendCheckData();

        //打开OpenPort
        bool COMState = false;  //串口打开状态  false：关闭   true：打开

        //申请测试平台数据List 以及定义相关的参数
        public List<TestData> TestDataList = new List<TestData>();  //定义测算平台总表
        int TestPlatformNum = 8;    //定义总的启动测试平台数目
        int TestPlatformNumTag = 1; //用于当前循环总数目  
        int ReSendCount = 1;        //定义重复发送的次数
        int ReSendCountTag = 0;     //用于当前发送的次数

        FormMsg Win_FormMsg = new FormMsg();
        FormMyMsgBox MyMsgBox = new FormMyMsgBox();

        public FormMain()
        {
            InitializeComponent();
            //初始化更新消息文本框内容委托及委托事件
            COMConnect.OnExecUploadEvent += OnCOMFormMainEvent;
            OnComReceiveMsgEvent = new ComReceiveMsgEvent(OnCOMFormMainCallBack);

            //此为Lambda封装方式
            COMConnect.OnCOMErrMsgEvent += OnCOMErrMsgFormMainEvent;
            //this.IsMdiContainer = true;

        }


        /// <summary>
        /// 主窗口 窗口加载的时候，执行相应的操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormMain_Load(object sender, EventArgs e)
        {
            //设置串口界面初始化
            string[] ports = SerialPort.GetPortNames().OrderBy(p => p).ToArray();
            COM1.Items.Clear();
            foreach (string port in ports)
            {
                COM1.Items.Add(port);
            }
            //设置下拉索引
            COM1.SelectedIndex = 0;
            BaudRate1.SelectedIndex = 2;

            //把对应的测试类装到全局List
            for (int i = 1; i <= TestPlatformNum; i++)
            {
                var list = new TestData(i);
                TestDataList.Add(list);
            }

            //开启定时器

            TimerMain.Interval = 500;//设置定时器时间 单位ms
            TimerMain.Tick += new EventHandler(TimerEventCallBack);//添加事件
            TimerMain.Enabled = true;
            TimerMain.Start();

            //开启数据库检测线程
            Thread Thread1 = new Thread(new ThreadStart(SqlConnCheckThread));
            Thread1.IsBackground = true;
            Thread1.Start();


        }

        public void SqlConnCheckThread()
        {
            string Msg = "";
            BaseDao dao = new BaseDao();
            
            while (true)
            {
                try
                {
                    dao.CheckConnection();
                    Msg = "OK";                                   
                }
                catch (Exception)
                {
                    Msg = "Error";
                    //throw;
                }
                BeginInvoke(new SqlConnThreadMsg(ChangeSqlConnLable), Msg);
                Thread.Sleep(10*1000);
                //Msg = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                //this.SqlConnLab.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

            }



        }

        /// <summary>
        /// 更新数据库连接状态
        /// </summary>
        /// <param name="Msg"></param>
        private void ChangeSqlConnLable(string Msg)
        {
            if (Msg == "OK")
            {
                this.SqlConnLab.Text = "数据库连接正常";
                this.SqlConnLab.ForeColor= System.Drawing.SystemColors.HotTrack;
            }
            else
            {
                this.SqlConnLab.Text = "数据库连接失败";
                this.SqlConnLab.ForeColor = System.Drawing.Color.Red;
            }
            
        }

        //COMConnect接收消息函数
        public void OnCOMFormMainEvent(string strMsg,byte[] buff)
        {
            BeginInvoke(OnComReceiveMsgEvent, strMsg,buff);
        }

        public void OnCOMErrMsgFormMainEvent(string strMsg)
        {
            BeginInvoke(
                new Action(() => { OnCOMErrMsgCallBack(strMsg); })
            );
        }

        /// <summary>
        /// Form窗口对于COMConnect错误的回调
        /// </summary>
        /// <param name="strMsg"></param>
        public void OnCOMErrMsgCallBack(string strMsg)
        {
            MessageBox.Show(strMsg);
        }

        /// <summary>
        /// Form窗口对于COMConnect的消息回调
        /// </summary>
        /// <param name="strMsg"></param>
        private void OnCOMFormMainCallBack(string strMsg, byte[] buff)
        {
            //首先获取CANID
            string CAN_ID = buff[4].ToString("X2") + buff[3].ToString("X2");
            var temptestdata = TestDataList.Find(r => r.CAN_ID == CAN_ID);
            if (temptestdata==null || temptestdata.CAN_ID=="")
            {
                return;
            }
            switch (temptestdata.Stage)
            {
                case TestState.free:
                    break;
                case TestState.ready:
                    if (buff[5] == 0x01)    //表示板子正在测试
                    {
                        temptestdata.Stage = TestState.running;
                        COMConnect.WaitForRecive = false;
                        //这里处理 循环到底部后，再返回到第一个
                        TestPlatformNumTag++;
                        if (TestPlatformNumTag > TestPlatformNum) TestPlatformNumTag = 1;
                        ReSendCountTag = 0;
                        TimerCount = 0;

                    }
                    if (buff[5] == 0x07)    //  表示接收到了对应的启动指示
                    {
                        temptestdata.Stage = TestState.running;
                        COMConnect.WaitForRecive = false;
                        ((Label)Controls.Find("Test" + temptestdata.PlatformNum + "_StateLabel", true)[0]).Text = "运行中";
                        ((Label)Controls.Find("Test" + temptestdata.PlatformNum + "_StateLabel", true)[0]).ForeColor = Color.Orchid;
                        COMConnect.WaitForRecive = false;

                        //这里处理 循环到底部后，再返回到第一个
                        TestPlatformNumTag++;
                        if (TestPlatformNumTag > TestPlatformNum) TestPlatformNumTag = 1;
                        ReSendCountTag = 0;
                        TimerCount = 0;
                        //temptestdata.
                    }
                    break;
                case TestState.running:
                    if (buff[5] == 0x01)    //表示板子正在测试
                    {
                        temptestdata.Stage = TestState.running;
                        COMConnect.WaitForRecive = false;
                        //这里处理 循环到底部后，再返回到第一个
                        TestPlatformNumTag++;
                        if (TestPlatformNumTag > TestPlatformNum) TestPlatformNumTag = 1;
                        ReSendCountTag = 0;
                        TimerCount = 0;


                    }
                    if (buff[5] == 0x03)    //表示接收数据报告 进行解析
                    {
                        
                        if (buff.Length == 935)
                        {
                            var temparr= buff.Skip(12).Take(918).ToArray();
                            temptestdata.AnalysisData(temparr);
                            if (IsSqlConnection)
                            {
                                temptestdata.InsertSql();
                            }
                            
                        }
                        temptestdata.Stage = TestState.report;
                        COMConnect.WaitForRecive = false;
                        //这里处理 循环到底部后，再返回到第一个
                        TestPlatformNumTag++;
                        if (TestPlatformNumTag > TestPlatformNum) TestPlatformNumTag = 1;
                        ReSendCountTag = 0;
                        TimerCount = 0;
                        if(temptestdata.ErrorInfo == "检测完毕，没有异常")
                        {
                            ((Label)Controls.Find("Test" + temptestdata.PlatformNum + "_StateLabel", true)[0]).Text = "测试结束";
                            ((Label)Controls.Find("Test" + temptestdata.PlatformNum + "_StateLabel", true)[0]).ForeColor = Color.Green;
                        }
                        else
                        {
                            ((Label)Controls.Find("Test" + temptestdata.PlatformNum + "_StateLabel", true)[0]).Text = "测试结束,有异常";
                            ((Label)Controls.Find("Test" + temptestdata.PlatformNum + "_StateLabel", true)[0]).ForeColor = Color.Red;
                        }
                        //temptestdata.CAN_ID = "";
                        
                        
                    }

                    break;
                case TestState.report:



                    break;
                case TestState.stop:
                    if (buff[5]== 0x09)
                    {
                        temptestdata.Stage = TestState.free;
                        COMConnect.WaitForRecive = false;
                        ((Label)Controls.Find("Test" + temptestdata.PlatformNum + "_StateLabel", true)[0]).Text = "已停止";
                        ((Label)Controls.Find("Test" + temptestdata.PlatformNum + "_StateLabel", true)[0]).ForeColor = Color.Orchid;
                        ((Button)Controls.Find("Test" + temptestdata.PlatformNum + "_StartBtn", true)[0]).Text = "运行";
                        //COMConnect.WaitForRecive = false;
                        ((TextBox)Controls.Find("Test" + temptestdata.PlatformNum + "_TxtId", true)[0]).ReadOnly = false;
                        ((TextBox)Controls.Find("Test" + temptestdata.PlatformNum + "_CANId", true)[0]).ReadOnly = false;
                        temptestdata.CAN_ID = "";
                        //这里处理 循环到底部后，再返回到第一个
                        TestPlatformNumTag++;
                        if (TestPlatformNumTag > TestPlatformNum) TestPlatformNumTag = 1;
                        ReSendCountTag = 0;
                        TimerCount = 0;
                    }        


                    break;
                default:
                    break;
            }

        }


        /// <summary>
        /// 定时器回调
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TimerEventCallBack(object sender, EventArgs e)
        {
            byte[] data;
            if (COMConnect.WaitForRecive == false)  //表示没有需要等待返回的信号，遍历列表发送
            {
                TestData item = TestDataList.Find(r => r.PlatformNum == TestPlatformNumTag);
                if (item != null)
                {
                    switch (item.Stage)
                    {
                        case TestState.free:
                            TestPlatformNumTag++;//表明是空闲，需要跳到下一个测试台
                            if (TestPlatformNumTag > TestPlatformNum) TestPlatformNumTag = 1;
                            break;

                        case TestState.ready:
                            //设置发送数据
                            item.ReportStr = "";
                            data = item.SendData;
                            //发送
                            COMConnect.COM1_DataSend(ref data);     //  获取发送变量发送
                            //设置相应的标识变量
                            COMConnect.WaitForRecive = true;
                            item.Stage = TestState.ready;
                            TimerCount = 0;
                            ReSendCountTag = 0;
                            return;

                            break;
                        case TestState.running:
                            //设置发送数据
                            
                            SendData.AssembleData_Polling(item.CAN_ID);
                            item.SendData = SendData.SendData;
                            data = item.SendData;
                            //发送
                            COMConnect.COM1_DataSend(ref data);
                            //设置相应的标识变量
                            COMConnect.WaitForRecive = true;
                            item.Stage = TestState.running;
                            TimerCount = 0;
                            ReSendCountTag = 0;
                            return;

                        case TestState.report:
                            //这里不做操作，直接返回
                            TestPlatformNumTag++;//表明是空闲，需要跳到下一个测试台
                            if (TestPlatformNumTag > TestPlatformNum) TestPlatformNumTag = 1;
                            break;

                        case TestState.stop:
                            //设置发送数据
                            SendData.AssembleData_Stop(item.CAN_ID);
                            item.SendData = SendData.SendData;
                            data = item.SendData;
                            //发送
                            COMConnect.COM1_DataSend(ref data);
                            //设置相应的标识变量
                            COMConnect.WaitForRecive = true;
                            item.Stage = TestState.stop;
                            TimerCount = 0;
                            ReSendCountTag = 0;
                            return;


                        default:
                            break;
                    }
                }
            }
            else        //这里等待相应的回复
            {
                //首先定时器计数自增
                TimerCount++;
                //下面判断经过的时间，然后做相应的操作
                TestData item = TestDataList.Find(r => r.PlatformNum == TestPlatformNumTag);
                if (TimerCount <= 10 || ReSendCountTag <= ReSendCount)      // 满足的重发条件 这里是定时器等待的时间  调试为10 实际为1
                {


                    switch (item.Stage)
                    {
                        case TestState.free:    //表示设置为空闲状态了 关闭计数
                            TestPlatformNumTag++;//表明是空闲，需要跳到下一个测试台
                            if (TestPlatformNumTag > TestPlatformNum) TestPlatformNumTag = 1;
                            ReSendCountTag = 0;
                            TimerCount = 0;
                            break;

                        case TestState.ready:
                            //设置发送数据
                            data = item.SendData;
                            //发送
                            COMConnect.COM1_DataSend(ref data);     //  获取发送变量发送
                            //设置相应的标识变量
                            COMConnect.WaitForRecive = true;
                            item.Stage = TestState.ready;

                            //这里是重复发送标识自增
                            ReSendCountTag++;
                            return;

                            break;
                        case TestState.running:
                            //设置发送数据
                            //SendCheckData SendData = new SendCheckData();
                            SendData.AssembleData_Polling(item.CAN_ID);
                            item.SendData = SendData.SendData;
                            data = item.SendData;
                            //发送
                            COMConnect.COM1_DataSend(ref data);
                            //设置相应的标识变量
                            COMConnect.WaitForRecive = true;
                            item.Stage = TestState.running;
                            
                            //这里是重复发送标识自增
                            ReSendCountTag++;
                            return;

                        case TestState.stop:
                            //设置发送数据
                            SendData.AssembleData_Stop(item.CAN_ID);
                            item.SendData = SendData.SendData;
                            data = item.SendData;
                            //发送
                            COMConnect.COM1_DataSend(ref data);
                            //设置相应的标识变量
                            COMConnect.WaitForRecive = true;
                            item.Stage = TestState.stop;

                            //这里是重复发送标识自增
                            ReSendCountTag++;
                            return;

                        case TestState.report:
                            break;
                        default:
                            break;
                    }

                }
                else    //不满足重发条件，表明已经错误了
                {
                    
                    ((TextBox)Controls.Find("Test" + item.PlatformNum + "_TxtId", true)[0]).ReadOnly = false;
                    ((TextBox)Controls.Find("Test" + item.PlatformNum + "_CANId", true)[0]).ReadOnly = false;
                    ((Label)Controls.Find("Test" + item.PlatformNum + "_StateLabel", true)[0]).Text = "485通信超时";
                    ((Button)Controls.Find("Test" + item.PlatformNum + "_StartBtn", true)[0]).Text = "运行";
                    item.CAN_ID = "";//把CANId清除
                    //下面进行停止操作
                    item.Stage = TestState.free;
                    TimerCount = 0;
                    ReSendCountTag = 0;
                    COMConnect.WaitForRecive = false;       //切回去 停止等待



                }
                



            }

            //MessageBox.Show("aaaa");
            //TimerMain.Enabled = false;
            //TimerMain.Stop();
            
        }

        private void BtnCOM_Click(object sender, EventArgs e)
        {
            if (COMState == false)
            {

                COMConnect.COM1.PortName = COM1.Text;
                COMConnect.COM1.BaudRate = int.Parse(BaudRate1.Text);
                COMConnect.COM1.DataBits = 8;
                COMConnect.COM1.StopBits = (StopBits)1;
                COMConnect.COM1.ReadTimeout = 500;

                string result = COMConnect.ComOpen();
                if ("OK"==result)
                {
                    COMState = true;
                    BtnCOM.Text = "关闭串口";
                }
                else
                {
                    COMState = false;
                    BtnCOM.Text = "打开串口";
                    MessageBox.Show(result);
                }
                //打开


            }
            else
            {
                COMConnect.ComClose();
                
                COMState = false;
                BtnCOM.Text = "打开串口";
                //this.pictureBox.Image = global::SerialDemo.Properties.Resources.can1;

                //sp1.DataReceived -= new SerialDataReceivedEventHandler(sp1_DataReceived);

            }


        }

        /// <summary>
        /// 测试台1运行按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Test_StartBtn_Click(object sender, EventArgs e)
        {
            if (COMState==false)
            {
                MessageBox.Show("请先打开串口！", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            Button nowBtnClicked = (Button)sender;
            string num = nowBtnClicked.Name.Substring(4,1); //Test1_TxtId
            string Id=((TextBox)Controls.Find("Test" + num + "_TxtId", true)[0]).Text;
            string CAN_ID = ((TextBox)Controls.Find("Test" + num + "_CANId", true)[0]).Text;
            Label tempLabel = (Label)Controls.Find("Test" + num + "_StateLabel", true)[0];
           

            if (Id=="")
            {
                MessageBox.Show("请先填写电机编号！", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            try
            {
                int.Parse(CAN_ID);
                if (CAN_ID.Length != 4)
                {
                    MessageBox.Show("CAN_ID:输入错误", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
            }
            catch (Exception ex)
            {

                MessageBox.Show("CAN_ID:"+ex.Message, "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }


            



            //((TextBox)Controls.Find("Test" + num + "_TxtId", true)[0]).Enabled = false;
            TestData item = TestDataList.Find(r => r.PlatformNum == int.Parse(num));

            if (nowBtnClicked.Text == "运行")
            {
                if (null != TestDataList.Find(r => r.CAN_ID == CAN_ID))
                {
                    MessageBox.Show("存在相同的CAN_ID:", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
                item.MotorId = Id;
                switch (item.Stage)
                {
                    case TestState.free:
                        tempLabel.Text = "启动中。。。";
                        tempLabel.ForeColor = Color.Orange;
                        ((TextBox)Controls.Find("Test" + num + "_TxtId", true)[0]).ReadOnly = true;
                        ((TextBox)Controls.Find("Test" + num + "_CANId", true)[0]).ReadOnly = true;
                        //下面查询CANID是否有重复的


                        SendCheckData SendData = new SendCheckData();
                        SendData.AssembleData_Begin(CAN_ID);
                        TestDataList.Find(r => r.PlatformNum == int.Parse(num)).CAN_ID = CAN_ID;
                        TestDataList.Find(r => r.PlatformNum == int.Parse(num)).SendData = SendData.SendData;
                        TestDataList.Find(r => r.PlatformNum == int.Parse(num)).Stage = TestState.ready;
                        nowBtnClicked.Text = "停止";

                        //AddPlatform(num, CAN_ID);

                        break;

                    default:
                        break;
                }
            }
            else    //  停止   这里暂时跟新UI，实际需要发送串口信息让其停止
            {
                nowBtnClicked.Text = "停止中";
                tempLabel.Text = "停止中";
                tempLabel.ForeColor = System.Drawing.SystemColors.HotTrack;

                //TestDataList.Find(r => r.PlatformNum == int.Parse(num)).CAN_ID = "";
                TestDataList.Find(r => r.PlatformNum == int.Parse(num)).Stage = TestState.stop;
                ((TextBox)Controls.Find("Test" + num + "_TxtId", true)[0]).ReadOnly = false;
                ((TextBox)Controls.Find("Test" + num + "_CANId", true)[0]).ReadOnly = false;

            }

        }


        //添加测试台，让定时器回调去处理相应的操作
        public void AddPlatform(string num,string CAN_ID)
        {
            SendCheckData SendData = new SendCheckData();
            SendData.AssembleData_Begin(CAN_ID);
            TestData td = new TestData(int.Parse(num), CAN_ID);
            td.SendData = SendData.SendData;
            TestDataList.Add(td);

        }

        //轮训操作
        public void PollingPlatform(ref TestData td)
        {
            SendCheckData SendData = new SendCheckData();
            SendData.AssembleData_Polling(td.CAN_ID);
            td.SendData = SendData.SendData;
        }


        private void Btn_CheckErr_Click(object sender, EventArgs e)
        {
            //Test1_CheckBtn
            Button nowBtnClicked = (Button)sender;
            string num = nowBtnClicked.Name.Substring(4, 1); //Test1_TxtId
            var labelstr = ((Label)Controls.Find("Test" + num + "_StateLabel", true)[0]).Text;
            if (!labelstr.Contains("测试结束")) return;
            TestData item = TestDataList.Find(r => r.PlatformNum == int.Parse(num));
            ((TextBox)(Win_FormMsg.Controls.Find("textBox", true)[0])).Text = item.ReportStr;
            Win_FormMsg.Show();
            //foreach (Form fm in Application.OpenForms)
            //{
            //    if (fm.Name == "FormMsg")
            //    {
            //        FormMsg frm = fm as FormMsg;
            //        ((TextBox)(frm.Controls.Find("textBox", true)[0])).Text = "运行中";
            //        return;
            //    }
            //}

            //Win_FormMsg.Controls.Find
            //Win_FormMsg.ShowDialog();



        }


        private void Btn_ExportExcel_Click(object sender,EventArgs e)
        {
            MyMsgBox.Hide();
            Button nowBtnClicked = (Button)sender;
            string num = nowBtnClicked.Name.Substring(4, 1); //Test1_TxtId
            string TxtId = ((TextBox)Controls.Find("Test" + num + "_TxtId", true)[0]).Text;
            var labelstr = ((Label)Controls.Find("Test" + num + "_StateLabel", true)[0]).Text;
            if (!labelstr.Contains("测试结束")) return;
            TestData item = TestDataList.Find(r => r.PlatformNum == int.Parse(num));
            ExcelExport export = new ExcelExport();
            XSSFWorkbook book = export.EstUserExport(item, TxtId);
            var ms = new NpoiMemoryStream();
            ms.AllowClose = false;
            book.Write(ms);
            ms.Flush();
            ms.Seek(0, SeekOrigin.Begin);
            var path = "C:\\AgingTest\\" + DateTime.Now.ToString(TxtId + "_yyyyMMddHHmmss") + ".xlsx";
            FileStream xlsfile = new FileStream(path, FileMode.Create,FileAccess.Write);
            xlsfile.Write(ms.ToArray(),0,(int)ms.Length);
            ms.Close();
            ms.Dispose();
            xlsfile.Flush();
            xlsfile.Close();
            xlsfile.Dispose();
            ((Label)(MyMsgBox.Controls.Find("label1", true)[0])).Text = "文件已保存在：" + path;
            MyMsgBox.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            MyMsgBox.Show();


        }






    }
}
